home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / compress / arc.zoo / arcio.c < prev    next >
C/C++ Source or Header  |  1989-01-29  |  8KB  |  294 lines

  1. /*
  2.  * $Header: arcio.c,v 1.9 88/07/31 18:49:19 hyc Exp $
  3.  */
  4.  
  5. /*  ARC - Archive utility - ARCIO
  6.  
  7.     Version 2.50, created on 04/22/87 at 13:25:20
  8.  
  9. (C) COPYRIGHT 1985,86 by System Enhancement Associates; ALL RIGHTS RESERVED
  10.  
  11.     By:     Thom Henderson
  12.  
  13.     Description:
  14.      This file contains the file I/O routines used to manipulate
  15.      an archive.
  16.  
  17.     Language:
  18.      Computer Innovations Optimizing C86
  19. */
  20. #include <stdio.h>
  21. #include "arc.h"
  22. #if    MTS
  23. #include <ctype.h>
  24. #endif
  25.  
  26. void    abort();
  27. #ifndef __STDC__
  28. int    strlen(), free();
  29. #endif
  30.  
  31. int
  32. readhdr(hdr, f)            /* read a header from an archive */
  33.     struct heads   *hdr;    /* storage for header */
  34.     FILE           *f;    /* archive to read header from */
  35. {
  36. #if    !MSDOS
  37.     unsigned char   dummy[28];
  38.     int             i;
  39. #endif
  40.     char            name[FNLEN];    /* filename buffer */
  41.     int             try = 0;/* retry counter */
  42.     static int      first = 1;    /* true only on first read */
  43.  
  44.     if (!f)            /* if archive didn't open */
  45.         return 0;    /* then pretend it's the end */
  46.     if (feof(f))        /* if no more data */
  47.         return 0;    /* then signal end of archive */
  48.  
  49.     if (fgetc(f) != ARCMARK) {    /* check archive validity */
  50.         if (warn) {
  51.             printf("An entry in %s has a bad header.", arcname);
  52.             nerrs++;
  53.         }
  54.         while (!feof(f)) {
  55.             try++;
  56.             if (fgetc(f) == ARCMARK) {
  57.                 ungetc(hdrver = fgetc(f), f);
  58.                 if (!(hdrver & 0x80) && hdrver <= ARCVER)
  59.                     break;
  60.             }
  61.         }
  62.  
  63.         if (feof(f) && first)
  64.             abort("%s is not an archive", arcname);
  65.  
  66.         if (changing && warn)
  67.             abort("%s is corrupted -- changes disallowed", arcname);
  68.  
  69.         if (warn)
  70.             printf("  %d bytes skipped.\n", try);
  71.  
  72.         if (feof(f))
  73.             return 0;
  74.     }
  75.     hdrver = fgetc(f);    /* get header version */
  76.     if (hdrver & 0x80)    /* sign bit? negative? */
  77.         abort("Invalid header in archive %s", arcname);
  78.     if (hdrver == 0)
  79.         return 0;    /* note our end of archive marker */
  80.     if (hdrver > ARCVER) {
  81.         fread(name, sizeof(char), FNLEN, f);
  82. #if    MTS
  83.         atoe(name, strlen(name));
  84. #endif
  85.         printf("I don't know how to handle file %s in archive %s\n",
  86.                name, arcname);
  87.         printf("I think you need a newer version of ARC.\n");
  88.         exit(1);
  89.     }
  90.     /* amount to read depends on header type */
  91.  
  92.     if (hdrver == 1) {    /* old style is shorter */
  93.         fread(hdr, sizeof(struct heads) - sizeof(long int), 1, f);
  94.         hdrver = 2;    /* convert header to new format */
  95.         hdr->length = hdr->size;    /* size is same when not
  96.                          * packed */
  97.     } else
  98. #if    MSDOS
  99.         fread(hdr, sizeof(struct heads), 1, f);
  100. #else
  101.         fread(dummy, 27, 1, f);
  102.  
  103.     for (i = 0; i < FNLEN; hdr->name[i] = dummy[i], i++);
  104. #if    MTS
  105.     (void) atoe(hdr->name, strlen(hdr->name));
  106. #endif
  107.     for (i = 0, hdr->size=0; i<4; hdr->size<<=8, hdr->size += dummy[16-i], i++);
  108.     hdr->date = (short) ((dummy[18] << 8) + dummy[17]);
  109.     hdr->time = (short) ((dummy[20] << 8) + dummy[19]);
  110.     hdr->crc = (short) ((dummy[22] << 8) + dummy[21]);
  111.     for (i = 0, hdr->length=0; i<4; hdr->length<<=8, hdr->length += dummy[26-i], i++);
  112. #endif
  113.  
  114.     if (hdr->date > olddate
  115.         || (hdr->date == olddate && hdr->time > oldtime)) {
  116.         olddate = hdr->date;
  117.         oldtime = hdr->time;
  118.     }
  119.     first = 0;
  120.     return 1;        /* we read something */
  121. }
  122.  
  123. void
  124. put_int(number, f)        /* write a 2 byte integer */
  125.     short           number;
  126.     FILE           *f;
  127. {
  128.     fputc((char) (number & 255), f);
  129.     fputc((char) (number >> 8), f);
  130. }
  131.  
  132. void
  133. put_long(number, f)        /* write a 4 byte integer */
  134.     long            number;
  135.     FILE           *f;
  136. {
  137.     put_int((short) (number & 0xFFFF), f);
  138.     put_int((short) (number >> 16), f);
  139. }
  140.  
  141. void
  142. writehdr(hdr, f)        /* write a header to an archive */
  143.     struct heads   *hdr;    /* header to write */
  144.     FILE           *f;    /* archive to write to */
  145. {
  146.     fputc(ARCMARK, f);        /* write out the mark of ARC */
  147.     fputc(hdrver, f);    /* write out the header version */
  148.     if (!hdrver)        /* if that's the end */
  149.         return;        /* then write no more */
  150. #if    MSDOS
  151.     fwrite(hdr, sizeof(struct heads), 1, f);
  152. #else
  153.     /* byte/word ordering hassles... */
  154. #if    MTS
  155.     etoa(hdr->name, strlen(hdr->name));
  156. #endif
  157.     fwrite(hdr->name, 1, FNLEN, f);
  158.     put_long(hdr->size, f);
  159.     put_int(hdr->date, f);
  160.     put_int(hdr->time, f);
  161.     put_int(hdr->crc, f);
  162.     put_long(hdr->length, f);
  163. #endif
  164.  
  165.     /* note the newest file for updating the archive timestamp */
  166.  
  167.     if (hdr->date > arcdate
  168.         || (hdr->date == arcdate && hdr->time > arctime)) {
  169.         arcdate = hdr->date;
  170.         arctime = hdr->time;
  171.     }
  172. }
  173.  
  174. void
  175. putc_tst(c, t)            /* put a character, with tests */
  176.     char            c;    /* character to output */
  177.     FILE           *t;    /* file to write to */
  178. {
  179.     c &= 0xff;
  180.     if (t) {
  181. #if    UNIX
  182.         fputc(c, t);
  183.         if (ferror(t))
  184.             abort("Write failed");
  185. #else
  186.         if (fputc(c, t) == EOF)
  187.             abort("Write fail (disk full?)");
  188. #endif
  189.     }
  190. }
  191.  
  192. /*
  193.  * NOTE:  The filecopy() function is used to move large numbers of bytes from
  194.  * one file to another.  This particular version has been modified to improve
  195.  * performance in Computer Innovations C86 version 2.3 in the small memory
  196.  * model.  It may not work as expected with other compilers or libraries, or
  197.  * indeed with different versions of the CI-C86 compiler and library, or with
  198.  * the same version in a different memory model.
  199.  * 
  200.  * The following is a functional equivalent to the filecopy() routine that
  201.  * should work properly on any system using any compiler, albeit at the cost
  202.  * of reduced performance:
  203.  * 
  204.  * filecopy(f,t,size) 
  205.  *      FILE *f, *t; long size; 
  206.  * { 
  207.  *      while(size--)
  208.  *              putc_tst(fgetc(f),t); 
  209.  * }
  210.  */
  211. #if    MSDOS
  212. #include <fileio2.h>
  213.  
  214. filecopy(f, t, size)        /* bulk file copier */
  215.     FILE           *f, *t;    /* files from and to */
  216.     long            size;    /* bytes to copy */
  217. {
  218.     char           *buf;    /* buffer pointer */
  219.     char           *alloc();/* buffer allocator */
  220.     unsigned int    bufl;    /* buffer length */
  221.     unsigned int    coreleft();    /* space available reporter */
  222.     unsigned int    cpy;    /* bytes being copied */
  223.     long            floc, tloc, fseek();    /* file pointers, setter */
  224.     struct regval   reg;    /* registers for DOS calls */
  225.  
  226.     if ((bufl = coreleft()) < 1000)    /* see how much space we have */
  227.         abort("Out of memory");
  228.     bufl -= 1000;        /* fudge factor for overhead */
  229.     if (bufl > 60000)
  230.         bufl = 60000;    /* avoid choking alloc() */
  231.     if (bufl > size)
  232.         bufl = size;    /* avoid wasting space */
  233.     buf = alloc(bufl);    /* allocate our buffer */
  234.  
  235.     floc = fseek(f, 0L, 1);    /* reset I/O system */
  236.     tloc = fseek(t, 0L, 1);
  237.  
  238.     segread(®.si);    /* set segment registers for DOS */
  239.  
  240.     while (size > 0) {    /* while more to copy */
  241.         reg.ax = 0x3F00;/* read from handle */
  242.         reg.bx = filehand(f);
  243.         reg.cx = bufl < size ? bufl : size;    /* amount to read */
  244.         reg.dx = buf;
  245.         if (sysint21(®, ®) & 1)
  246.             abort("Read fail");
  247.  
  248.         cpy = reg.ax;    /* amount actually read */
  249.         reg.ax = 0x4000;/* write to handle */
  250.         reg.bx = filehand(t);
  251.         reg.cx = cpy;
  252.         reg.dx = buf;
  253.         sysint21(®, ®);
  254.  
  255.         if (reg.ax != cpy)
  256.             abort("Write fail (disk full?)");
  257.  
  258.         size -= (long) cpy;
  259.     }
  260.  
  261.     free(buf);        /* all done with buffer */
  262. }
  263. #else
  264.  
  265. void
  266. filecopy(f, t, size)        /* bulk file copier */
  267.     FILE           *f, *t;    /* files from and to */
  268.     long            size;    /* bytes to copy */
  269. {
  270.     char           *buf;    /* buffer pointer */
  271. #ifndef __STDC__
  272.     char           *malloc();    /* buffer allocator */
  273. #endif
  274.     unsigned int    bufl;    /* buffer length */
  275.     unsigned int    cpy;    /* bytes being copied */
  276.  
  277.     bufl = 32760;
  278.     if (bufl > size)
  279.         bufl = size;    /* don't waste space */
  280.  
  281.     buf = malloc(bufl);
  282.  
  283.     while (size > 0) {
  284.         cpy = fread(buf, sizeof(char),
  285.             bufl < size ? bufl : (unsigned short) size, f);
  286.         if (fwrite(buf, sizeof(char), cpy, t) != cpy)
  287.             abort("Write fail (no space?)");
  288.         size -= cpy;
  289.     }
  290.  
  291.     free(buf);
  292. }
  293. #endif
  294.